package com.rzx.mybackend.utils;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBucket;
import org.redisson.api.RLock;
import org.redisson.api.RMap;
import org.redisson.api.RSet;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * RedissonUtils
 *
 * @author renzhexian
 * @date 2025/10/13
 */

@Component
@RequiredArgsConstructor
@Slf4j
public class RedissonUtil {

    private final RedissonClient redissonClient;

    /**
     * 设置字符串类型的缓存值
     *
     * @param key   缓存键
     * @param value 缓存值
     */
    public void setString(String key, Object value) {
        if (key == null || value == null) {
            log.warn("设置缓存失败，key或value为空，key: {}", key);
            return;
        }
        try {
            RBucket<Object> bucket = redissonClient.getBucket(key);
            bucket.set(value);
            log.debug("设置缓存成功，key: {}", key);
        } catch (Exception e) {
            log.error("设置缓存异常，key: {}", key, e);
        }
    }

    /**
     * 设置带过期时间的字符串缓存值
     *
     * @param key      缓存键
     * @param value    缓存值
     * @param timeout  过期时间
     * @param timeUnit 时间单位
     */
    public void setString(String key, Object value, long timeout, TimeUnit timeUnit) {
        if (key == null || value == null) {
            log.warn("设置缓存失败，key或value为空，key: {}", key);
            return;
        }
        try {
            RBucket<Object> bucket = redissonClient.getBucket(key);
            bucket.set(value, timeout, timeUnit);
            log.debug("设置缓存成功，key: {}，过期时间: {} {}", key, timeout, timeUnit);
        } catch (Exception e) {
            log.error("设置缓存异常，key: {}", key, e);
        }
    }

    /**
     * 获取字符串类型的缓存值
     *
     * @param key 缓存键
     * @param clazz 值类型
     * @return 缓存值
     */
    public <T> T getString(String key, Class<T> clazz) {
        if (key == null) {
            log.warn("获取缓存失败，key为空");
            return null;
        }
        try {
            RBucket<T> bucket = redissonClient.getBucket(key);
            T value = bucket.get();
            log.debug("获取缓存成功，key: {}", key);
            return value;
        } catch (Exception e) {
            log.error("获取缓存异常，key: {}", key, e);
            return null;
        }
    }

    /**
     * 删除指定key的缓存
     *
     * @param key 缓存键
     * @return 是否删除成功
     */
    public boolean delete(String key) {
        if (key == null) {
            log.warn("删除缓存失败，key为空");
            return false;
        }
        try {
            RBucket<Object> bucket = redissonClient.getBucket(key);
            boolean result = bucket.delete();
            log.debug("删除缓存{}，key: {}", result ? "成功" : "失败", key);
            return result;
        } catch (Exception e) {
            log.error("删除缓存异常，key: {}", key, e);
            return false;
        }
    }

    /**
     * 检查key是否存在
     *
     * @param key 缓存键
     * @return 是否存在
     */
    public boolean exists(String key) {
        if (key == null) {
            log.warn("检查缓存存在性失败，key为空");
            return false;
        }
        try {
            RBucket<Object> bucket = redissonClient.getBucket(key);
            boolean result = bucket.isExists();
            log.debug("检查缓存存在性：{}，key: {}", result, key);
            return result;
        } catch (Exception e) {
            log.error("检查缓存存在性异常，key: {}", key, e);
            return false;
        }
    }

    /**
     * 获取分布式可重入锁
     *
     * @param lockKey 锁键
     * @return RLock对象
     */
    public RLock getLock(String lockKey) {
        if (lockKey == null || lockKey.isEmpty()) {
            log.warn("获取分布式锁失败，lockKey为空");
            return null;
        }
        try {
            RLock lock = redissonClient.getLock(lockKey);
            log.debug("获取分布式锁成功，lockKey: {}", lockKey);
            return lock;
        } catch (Exception e) {
            log.error("获取分布式锁异常，lockKey: {}", lockKey, e);
            return null;
        }
    }

    /**
     * 尝试获取分布式锁
     *
     * @param lockKey    锁键
     * @param waitTime   等待时间
     * @param leaseTime  持有时间
     * @param timeUnit   时间单位
     * @return 是否获取成功
     */
    public boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit timeUnit) {
        RLock lock = getLock(lockKey);
        if (lock == null) {
            return false;
        }
        try {
            boolean result = lock.tryLock(waitTime, leaseTime, timeUnit);
            log.debug("尝试获取分布式锁{}，lockKey: {}", result ? "成功" : "失败", lockKey);
            return result;
        } catch (Exception e) {
            log.error("尝试获取分布式锁异常，lockKey: {}", lockKey, e);
            return false;
        }
    }

    /**
     * 释放分布式锁
     *
     * @param lockKey 锁键
     */
    public void unLock(String lockKey) {
        RLock lock = getLock(lockKey);
        if (lock == null) {
            return;
        }
        try {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
                log.debug("释放分布式锁成功，lockKey: {}", lockKey);
            }
        } catch (Exception e) {
            log.error("释放分布式锁异常，lockKey: {}", lockKey, e);
        }
    }

    /**
     * 向Hash中添加字段
     *
     * @param key   Hash键
     * @param field 字段名
     * @param value 字段值
     */
    public void hSet(String key, String field, Object value) {
        if (key == null || field == null || value == null) {
            log.warn("设置Hash字段失败，参数为空，key: {}, field: {}", key, field);
            return;
        }
        try {
            RMap<String, Object> map = redissonClient.getMap(key);
            map.put(field, value);
            log.debug("设置Hash字段成功，key: {}, field: {}", key, field);
        } catch (Exception e) {
            log.error("设置Hash字段异常，key: {}, field: {}", key, field, e);
        }
    }

    /**
     * 获取Hash中的字段值
     *
     * @param key   Hash键
     * @param field 字段名
     * @param clazz 值类型
     * @return 字段值
     */
    public <T> T hGet(String key, String field, Class<T> clazz) {
        if (key == null || field == null) {
            log.warn("获取Hash字段失败，key或field为空，key: {}, field: {}", key, field);
            return null;
        }
        try {
            RMap<String, T> map = redissonClient.getMap(key);
            T value = map.get(field);
            log.debug("获取Hash字段成功，key: {}, field: {}", key, field);
            return value;
        } catch (Exception e) {
            log.error("获取Hash字段异常，key: {}, field: {}", key, field, e);
            return null;
        }
    }

    /**
     * 向Set中添加元素
     *
     * @param key    Set键
     * @param values 元素值
     */
    public void sAdd(String key, Object... values) {
        if (key == null || values == null || values.length == 0) {
            log.warn("向Set添加元素失败，参数为空，key: {}", key);
            return;
        }
        try {
            RSet<Object> set = redissonClient.getSet(key);
            set.addAll(java.util.Arrays.asList(values));
            log.debug("向Set添加元素成功，key: {}，元素数量: {}", key, values.length);
        } catch (Exception e) {
            log.error("向Set添加元素异常，key: {}", key, e);
        }
    }

    /**
     * 判断元素是否在Set中
     *
     * @param key   Set键
     * @param value 元素值
     * @return 是否存在
     */
    public boolean sIsMember(String key, Object value) {
        if (key == null || value == null) {
            log.warn("判断Set成员失败，参数为空，key: {}", key);
            return false;
        }
        try {
            RSet<Object> set = redissonClient.getSet(key);
            boolean result = set.contains(value);
            log.debug("判断Set成员：{}，key: {}，value: {}", result, key, value);
            return result;
        } catch (Exception e) {
            log.error("判断Set成员异常，key: {}，value: {}", key, value, e);
            return false;
        }
    }


}
